package com.lxk.service.outer;

import com.lxk.common.GsonUtils;
import com.lxk.service.component.RedisClient;
import com.lxk.utils.RedisNamingUtils;
import com.ning.http.client.AsyncHttpClient;
import com.ning.http.client.AsyncHttpClientConfig;
import com.ning.http.client.ListenableFuture;
import com.ning.http.client.Response;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.io.Serializable;

@Slf4j
@Component
public class GeoService implements InitializingBean {

    AsyncHttpClient asyncHttpClient = null;
    @Value("${geo.service.key}")
    private String geoServiceKey;
    @Value("${geo.service.url}")
    private String geoServiceUrl;

    @Resource
    private RedisClient redisClient;

    /**
     * 从接口获取ip转物理地址
     * 先从本地缓存获取，再从redis获取，最后调用接口
     * 目前接口免费调用限制次数，所以缓存起来，降低重复数据请求调用次数
     * @param ip
     * @return
     */
    @Cacheable(value = "ipAddrCache",key = "#ip")
    public GeoResponse fromIp2Addr(String ip) {
        log.info("ip查地址 :: ip:{}",ip);
        String responseStr = null;
        try{
            responseStr = redisClient.getKey(RedisNamingUtils.genIpGeoKey(ip));
        }catch (Exception e){
            log.error("geo cache response from redis :: ip:{},e:",ip,e);
        }
        if(StringUtils.isEmpty(responseStr)){
            responseStr = invokeGeoApi(ip);
        }
        GeoResponse geoResponse = null;
        if(!StringUtils.isEmpty(responseStr)){
            try{
                redisClient.setex(RedisNamingUtils.genIpGeoKey(ip),responseStr,1000*60*60*6);
                geoResponse = GsonUtils.getGson().fromJson(responseStr,GeoResponse.class);
            }catch (Exception e){
                log.error("responseStr deserialize fail :: responseStr:{},e:",responseStr,e);
            }
        }
        return geoResponse;
    }

    String invokeGeoApi(String ip){
        String responseStr = null;
        StringBuilder urlBuilder = new StringBuilder();
        String url = urlBuilder.append(geoServiceUrl)
                .append("?")
                .append("key=").append(geoServiceKey)
                .append("&")
                .append("ip=").append(ip)
                .toString();

        AsyncHttpClient.BoundRequestBuilder builder = asyncHttpClient.prepareGet(url);
        ListenableFuture<Response> future = asyncHttpClient.executeRequest(builder.build());
        try{
            Response response = future.get();
            responseStr = response.getResponseBody();
            log.info("geo api invoke :: request:{} response:{}",url,responseStr);
        }catch (Exception e){
            log.error("根据ip转换地址 :: ip:{},e:",ip,e);
        }
        return responseStr;
    }

    @Data
    public static class GeoResponse implements Serializable {
        private  String status;

        private String info;

        private String infocode;

        private String province;

        private String city;

        private String adcode;

        private String rectangle;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        AsyncHttpClientConfig asyncHttpClientConfig = new AsyncHttpClientConfig.Builder()
                .setConnectTimeout(2000)
                .setReadTimeout(3000)
                .setRequestTimeout(6000)
                .build();
        asyncHttpClient = new AsyncHttpClient(asyncHttpClientConfig);
    }

}
